package com.lifeverse.service;

import com.lifeverse.entity.ServiceDiscovery;
import com.lifeverse.entity.enums.HealthStatus;
import com.lifeverse.repository.ServiceDiscoveryRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 服务发现服务
 */
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional
public class ServiceDiscoveryService {

    private final ServiceDiscoveryRepository serviceDiscoveryRepository;
    private final AlertService alertService;
    private final Random random = new Random();

    /**
     * 注册服务实例
     */
    public ServiceDiscovery registerService(String serviceName, String instanceId, String host, 
                                          Integer port, String version, String environment, 
                                          Map<String, String> metadata, java.util.Set<String> tags) {
        
        Optional<ServiceDiscovery> existingService = serviceDiscoveryRepository.findByInstanceId(instanceId);
        
        if (existingService.isPresent()) {
            // 更新现有服务
            ServiceDiscovery service = existingService.get();
            service.setServiceName(serviceName);
            service.setHost(host);
            service.setPort(port);
            service.setVersion(version);
            service.setEnvironment(environment);
            service.setMetadata(metadata);
            service.setTags(tags);
            service.setEnabled(true);
            service.updateHeartbeat();
            
            ServiceDiscovery savedService = serviceDiscoveryRepository.save(service);
            log.info("更新服务注册: {} - {} - {}:{}", serviceName, instanceId, host, port);
            return savedService;
        }

        // 创建新服务注册
        ServiceDiscovery service = new ServiceDiscovery();
        service.setServiceName(serviceName);
        service.setInstanceId(instanceId);
        service.setHost(host);
        service.setPort(port);
        service.setVersion(version);
        service.setEnvironment(environment);
        service.setStatus(HealthStatus.HEALTHY);
        service.setMetadata(metadata);
        service.setTags(tags);
        service.setRegisteredAt(LocalDateTime.now());
        service.updateHeartbeat();
        service.setEnabled(true);

        ServiceDiscovery savedService = serviceDiscoveryRepository.save(service);
        log.info("注册新服务: {} - {} - {}:{}", serviceName, instanceId, host, port);

        return savedService;
    }

    /**
     * 注销服务实例
     */
    public void deregisterService(String instanceId) {
        Optional<ServiceDiscovery> serviceOpt = serviceDiscoveryRepository.findByInstanceId(instanceId);
        if (serviceOpt.isPresent()) {
            ServiceDiscovery service = serviceOpt.get();
            service.setEnabled(false);
            service.setStatus(HealthStatus.DOWN);
            serviceDiscoveryRepository.save(service);
            log.info("注销服务: {} - {}", service.getServiceName(), instanceId);
        }
    }

    /**
     * 更新服务心跳
     */
    public void updateHeartbeat(String instanceId) {
        Optional<ServiceDiscovery> serviceOpt = serviceDiscoveryRepository.findByInstanceId(instanceId);
        if (serviceOpt.isPresent()) {
            ServiceDiscovery service = serviceOpt.get();
            service.updateHeartbeat();
            serviceDiscoveryRepository.save(service);
            log.debug("更新服务心跳: {} - {}", service.getServiceName(), instanceId);
        }
    }

    /**
     * 发现服务实例
     */
    @Transactional(readOnly = true)
    public List<ServiceDiscovery> discoverServices(String serviceName) {
        LocalDateTime heartbeatThreshold = LocalDateTime.now().minusSeconds(90); // 90秒心跳超时
        return serviceDiscoveryRepository.findAvailableServicesByName(serviceName, heartbeatThreshold);
    }

    /**
     * 获取所有可用服务
     */
    @Transactional(readOnly = true)
    public List<ServiceDiscovery> getAllAvailableServices() {
        LocalDateTime heartbeatThreshold = LocalDateTime.now().minusSeconds(90);
        return serviceDiscoveryRepository.findAvailableServices(heartbeatThreshold);
    }

    /**
     * 负载均衡选择服务实例
     */
    @Transactional(readOnly = true)
    public Optional<ServiceDiscovery> selectServiceInstance(String serviceName, String strategy) {
        List<ServiceDiscovery> availableServices = discoverServices(serviceName);
        
        if (availableServices.isEmpty()) {
            return Optional.empty();
        }

        switch (strategy.toLowerCase()) {
            case "random":
                return Optional.of(availableServices.get(random.nextInt(availableServices.size())));
            
            case "round_robin":
                // 简单的轮询实现（实际应用中需要更复杂的状态管理）
                return Optional.of(availableServices.get(0));
            
            case "weighted":
                // 基于权重选择
                return selectByWeight(availableServices);
            
            case "least_connections":
                // 选择连接数最少的实例（这里简化为选择权重最高的）
                return availableServices.stream()
                        .max((s1, s2) -> Integer.compare(s1.getWeight(), s2.getWeight()));
            
            default:
                return Optional.of(availableServices.get(0));
        }
    }

    /**
     * 基于权重选择服务实例
     */
    private Optional<ServiceDiscovery> selectByWeight(List<ServiceDiscovery> services) {
        int totalWeight = services.stream().mapToInt(ServiceDiscovery::getWeight).sum();
        if (totalWeight <= 0) {
            return Optional.of(services.get(0));
        }

        int randomWeight = random.nextInt(totalWeight);
        int currentWeight = 0;

        for (ServiceDiscovery service : services) {
            currentWeight += service.getWeight();
            if (randomWeight < currentWeight) {
                return Optional.of(service);
            }
        }

        return Optional.of(services.get(0));
    }

    /**
     * 根据标签查询服务
     */
    @Transactional(readOnly = true)
    public List<ServiceDiscovery> findServicesByTag(String tag) {
        return serviceDiscoveryRepository.findByTag(tag);
    }

    /**
     * 根据环境查询服务
     */
    @Transactional(readOnly = true)
    public List<ServiceDiscovery> findServicesByEnvironment(String environment) {
        return serviceDiscoveryRepository.findByEnvironment(environment);
    }

    /**
     * 获取服务统计信息
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getServiceStatistics() {
        Map<String, Object> statistics = new java.util.HashMap<>();

        // 按服务统计实例数量
        List<Object[]> instanceCounts = serviceDiscoveryRepository.countInstancesByService();
        Map<String, Long> instanceStats = instanceCounts.stream()
                .collect(Collectors.toMap(
                        row -> (String) row[0],
                        row -> (Long) row[1]
                ));
        statistics.put("instanceCounts", instanceStats);

        // 按状态统计
        List<Object[]> statusCounts = serviceDiscoveryRepository.countByStatus();
        Map<String, Long> statusStats = statusCounts.stream()
                .collect(Collectors.toMap(
                        row -> ((HealthStatus) row[0]).name(),
                        row -> (Long) row[1]
                ));
        statistics.put("statusCounts", statusStats);

        // 按环境统计
        List<Object[]> environmentCounts = serviceDiscoveryRepository.countByEnvironment();
        Map<String, Long> environmentStats = environmentCounts.stream()
                .collect(Collectors.toMap(
                        row -> (String) row[0],
                        row -> (Long) row[1]
                ));
        statistics.put("environmentCounts", environmentStats);

        // 服务健康状态分布
        List<Object[]> healthDistribution = serviceDiscoveryRepository.getServiceHealthDistribution();
        statistics.put("healthDistribution", healthDistribution);

        return statistics;
    }

    /**
     * 定时检查心跳过期的服务
     */
    @Scheduled(fixedRate = 60000) // 每分钟检查一次
    public void checkExpiredHeartbeats() {
        LocalDateTime threshold = LocalDateTime.now().minusSeconds(90);
        List<ServiceDiscovery> expiredServices = serviceDiscoveryRepository.findExpiredHeartbeatServices(threshold);

        for (ServiceDiscovery service : expiredServices) {
            service.markAsUnavailable("心跳超时");
            serviceDiscoveryRepository.save(service);
            
            // 创建服务不可用告警
            createServiceUnavailableAlert(service);
            
            log.warn("服务心跳过期: {} - {} - 最后心跳: {}", 
                    service.getServiceName(), service.getInstanceId(), service.getLastHeartbeat());
        }

        if (!expiredServices.isEmpty()) {
            log.info("检查到 {} 个心跳过期的服务", expiredServices.size());
        }
    }

    /**
     * 创建服务不可用告警
     */
    private void createServiceUnavailableAlert(ServiceDiscovery service) {
        String alertName = "服务不可用";
        String description = String.format("服务实例 %s (%s) 心跳超时，服务不可用", 
                service.getInstanceId(), service.getServiceAddress());
        
        Map<String, String> labels = Map.of(
                "service", service.getServiceName(),
                "instance", service.getInstanceId(),
                "host", service.getHost(),
                "port", service.getPort().toString()
        );
        
        Map<String, String> annotations = Map.of(
                "last_heartbeat", service.getLastHeartbeat().toString(),
                "environment", service.getEnvironment() != null ? service.getEnvironment() : "",
                "version", service.getVersion() != null ? service.getVersion() : ""
        );

        alertService.createAlert(alertName, description, 
                com.lifeverse.entity.enums.AlertSeverity.WARNING,
                service.getServiceName(), "service_unavailable", 
                labels, annotations, null, null);
    }

    /**
     * 清理过期的服务注册记录
     */
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    public void cleanupExpiredServices() {
        LocalDateTime threshold = LocalDateTime.now().minusDays(7); // 7天前
        serviceDiscoveryRepository.deleteExpiredServices(threshold);
        log.info("清理过期服务注册记录完成");
    }

    /**
     * 获取服务版本信息
     */
    @Transactional(readOnly = true)
    public List<String> getServiceVersions(String serviceName) {
        return serviceDiscoveryRepository.findVersionsByServiceName(serviceName);
    }

    /**
     * 更新服务权重
     */
    public ServiceDiscovery updateServiceWeight(String instanceId, Integer weight) {
        Optional<ServiceDiscovery> serviceOpt = serviceDiscoveryRepository.findByInstanceId(instanceId);
        if (serviceOpt.isEmpty()) {
            throw new RuntimeException("服务实例不存在: " + instanceId);
        }

        ServiceDiscovery service = serviceOpt.get();
        service.setWeight(weight);
        
        ServiceDiscovery savedService = serviceDiscoveryRepository.save(service);
        log.info("更新服务权重: {} - {} - 权重: {}", 
                service.getServiceName(), instanceId, weight);

        return savedService;
    }

    /**
     * 获取服务注册趋势
     */
    @Transactional(readOnly = true)
    public List<Object[]> getRegistrationTrend(int days) {
        LocalDateTime since = LocalDateTime.now().minusDays(days);
        return serviceDiscoveryRepository.getRegistrationTrend(since);
    }
}